var db = require("mysql");
var conf = require('../../../config');
var logger = require("log4js").getLogger('bussiness=>db=>db.js');
var Promise = require('promise');


var client = function () {

};

var pool = db.createPool({
    host: conf.db.host,
    port: conf.db.port,
    user: conf.db.user,
    password: conf.db.password,
    database: conf.db.database,
    charset: conf.db.charset,
    insecureAuth: true
});


//普通查询 
client.query = function (sql) {
    return new Promise(function (fulfill, reject) {
        logger.debug('query sql : ' + sql);
        pool.getConnection(function (err, connection) {
            if (err) {
                logger.error('db connection error : ' + err);
                reject(err);
                return;
            }
            connection.config.queryFormat = null;
            // Use the connection
            _common(connection, sql, null, fulfill, reject);
        });
    });
};

//支持 a=:a查询
client.queryFormat = function (sql, obj) {
    return new Promise(function (fulfill, reject) {
        logger.debug('query sql : ' + sql);
        pool.getConnection(function (err, connection) {
            if (err) {
                reject(err);
                logger.error('db connection error : ' + err);
                return;
            }
            connection.config.queryFormat = function (query, values) {
                if (!values) return query;
                return query.replace(/\:(\w+)/g, function (txt, key) {
                    if (values.hasOwnProperty(key)) {
                        return this.escape(values[key]);
                    }
                    return txt;
                }.bind(this));
            };
            // Use the connection
            _common(connection, sql, obj, fulfill, reject);
        });
    });
};

client.save = function (sql, obj, connection) {
    return new Promise(function (fulfill, reject) {
        logger.debug('save sql : ' + sql);
        if(!connection){
            client.getConnection().then(function(connection){
                connection.config.queryFormat = null;
                _common(connection, sql, obj, fulfill, reject);
            }, function(err){
                reject(err);
            });
        }else{
            connection.config.queryFormat = null;
            _commonWithTransaction(connection, sql, obj, fulfill, reject);
        }
    });
};

client.update = function (sql, obj, connection) {
    return new Promise(function (fulfill, reject) {
        logger.debug('update sql : ' + sql);
        if(!connection){
            client.getConnection().then(function(connection){
                connection.config.queryFormat = function (query, values) {
                    if (!values) return query;
                    return query.replace(/\:(\w+)/g, function (txt, key) {
                        if (values.hasOwnProperty(key)) {
                            return this.escape(values[key]);
                        }
                        return txt;
                    }.bind(this));
                };
                _common(connection, sql, obj, fulfill, reject);
            }, function(err){
                reject(err);
            });
        }else{
            connection.config.queryFormat = function (query, values) {
                if (!values) return query;
                return query.replace(/\:(\w+)/g, function (txt, key) {
                    if (values.hasOwnProperty(key)) {
                        return this.escape(values[key]);
                    }
                    return txt;
                }.bind(this));
            };
            _commonWithTransaction(connection, sql, obj, fulfill, reject);
        }
    });

};

var _common = function (connection, sql, obj, fulfill, reject) {
    connection.query(sql, obj, function (err, rows) {
        try {
            if (err) {
                logger.error('db operator error : ' + err);
                reject(err);
                return;
            }
            logger.debug('operator back rows : ' + rows);
            fulfill(rows);
        } catch (e) {
            logger.error('db operator error : ' + e);
            reject(e);
        } finally {
            connection.release();
        }
    });
};

var _commonWithTransaction = function (connection, sql, obj, fulfill, reject) {
    connection.query(sql, obj, function (err, rows) {
        try {
            if (err) {
                logger.error('db operator error : ' + err);
                reject(err);
                return
            };
            logger.debug('operator back rows : ' + rows);
            fulfill(rows, connection);
        } catch (e) {
            logger.error('db operator error : ' + e);
            reject(e);
        }
    });
};

client.escape = function (obj) {
    return pool.escape(obj);
};

client.getConnection = function () {
    return new Promise(function (fulfill, reject) {
        pool.getConnection(function (err, connection) {
            if (err) {
                reject(err);
            } else {
                fulfill(connection);
            }
        });
    });
};

client.release = function (connection) {
    try {
        if (connection)connection.release();
    } catch (e) {
        logger.error('connection releaseed for transaction');
    }
};

client.beginTransaction = function(connection){
    return new Promise(function(fulfill, reject){
        connection.beginTransaction(function(err){
            if(err){
                reject(err);
            }else{
                fulfill(connection);
            }
        });
    });
};

client.rollback = function(connection){
    return new Promise(function(){
        connection.rollback(function(err){
            if(err){
                logger.error('rollback error : ' + err);
            }
            client.release(connection);
        });
    });
};

client.commit = function(connection){
    return new Promise(function(fulfill, reject){
        connection.commit(function(err){
            if(err){
                reject(err);
                client.rollback(connection);
            }else{
                fulfill(null);
                client.release(connection);
            }
        });
    });
};

client.pool = pool;

module.exports = client;